<script lang="ts" setup>
/**
 * Props
 * @width 组件宽度
 * 默认 100%
 *
 * @height 组件高度
 * 默认80rpx
 *
 * @type 输入框类型 --'text' | 'number' | 'digit' | 'idcard' | 'tel' | 'textarea' | 'password'
 * 默认 text
 *
 * @focus 自动聚焦
 * 默认 false
 *
 * @value 默认值
 *
 * @placeholder 占位符
 *
 * @clear 尾部清除按钮
 *
 * @right 文本右排列
 *
 * @autoHeight 'textarea' 时，是否自动调整高度
 * 默认 false
 *
 * @maxlength 最大输入长度
 *
 * @disabled 禁用
 *
 * @rules 校验规则
 * :rules="[
 *    { required: true, reg: /^\S/, message: '错误信息: 开头不能存在空格' } // 第一条规则
 *    { required: true } // 其他规则，符合上述规则后触发
 * ]"
 *
 * Emits
 * @value 当前value值
 *
 * @confirm 点击键盘确认时返回当前value值
 */
import { computed, PropType, ref, watch } from 'vue'
import Icon from '@C/Icon.vue'
import { hasUnit } from '@U/common'
import type { IObj } from '@/interface'

const props = defineProps({
  width: {
    type: String,
    required: false,
    default: '',
  },
  height: {
    type: String,
    required: false,
    default: '80',
  },
  styles: {
    type: Object as PropType<IObj>,
    required: false,
    default: () => ({}),
  },
  pldStyles: {
    type: Object as PropType<IObj>,
    required: false,
    default: () => ({}),
  },
  value: {
    type: String,
    required: false,
    default: '',
  },
  placeholder: {
    type: String,
    required: false,
    default: '请输入内容',
  },
  right: {
    type: Boolean,
    required: false,
    default: false,
  },
  type: {
    type: String as PropType<'text' | 'number' | 'digit' | 'idcard' | 'tel' | 'textarea' | 'password'>,
    required: false,
    default: 'text',
  },
  maxlength: {
    type: String,
    required: false,
    default: '-1',
  },
  clear: {
    type: Boolean,
    required: false,
    default: false,
  },
  disabled: {
    type: Boolean,
    required: false,
    default: false,
  },
  autoHeight: {
    type: Boolean,
    required: false,
    default: false,
  },
  focus: {
    type: Boolean,
    required: false,
    default: false,
  },
  rules: {
    type: Array as PropType<Array<{ required?: boolean, message: string, reg?: RegExp }>>,
    required: false,
    default: () => ([]),
  },
})
const emits = defineEmits(['update:value', 'value', 'confirm', 'errMessage'])

// 样式
const pldStyle = computed(() => {
  let style = ''
  Object.keys(props.pldStyles).forEach((key: string) => {
    style += `${key}: ${props.pldStyles[key]};`
  })
  return style
})

// input 值
const inputVal = ref(props.value || '')
const _propsVal = computed(() => JSON.stringify(props.value))
watch(
    () => inputVal.value,
    (newVal) => {
      emits('update:value', newVal)
      emits('value', newVal)
    },
)
watch(
    () => _propsVal.value,
    () => {
      inputVal.value = props.value
    },
)

// 确定
const inputConfirm = () => emits('confirm')

// 是否可清除
const hasClear = computed(() => (inputVal.value))
const clearVal = () => { inputVal.value = '' }

// 唤起键盘
const focusState = ref(props.focus && !props.disabled)
const inputBlur = () => {
  focusState.value = false
  if (props.rules?.length) {
    let err = ''
    props.rules.forEach((rule: IObj) => {
      if (err) return
      if (rule?.required && !inputVal.value) {
        err = rule?.message
      }
      if (rule?.reg && !(new RegExp(rule.reg).test(inputVal.value))) {
        err = rule?.message
      }
    })
    if (err) {
      emits('errMessage', err)
    }
  }
}

</script>

<template>
  <div class="prm-input">
    <Icon v-if="props.clear" :style="{opacity: hasClear ? 1 : 0}" class="prm-input-clear" name="icon-uploader-delete" size="40" @tap="clearVal" />
    <input
      v-if="type !== 'textarea'"
      v-model.trim="inputVal"
      :adjust-position="true"
      :disabled="disabled"
      :focus="focusState"
      :maxlength="(+maxlength)"
      :password="type === 'password'"
      :placeholder="placeholder"
      :placeholder-style="`${pldStyle}`"
      :style="{
        width: `${width ? hasUnit(width) : '100%'}`,
        height: hasUnit(height),
        textAlign: `${right ? 'right' : 'left'}`,
        paddingRight: `${clear ? '80rpx' : '0'}`,
        ...styles,
      }"
      :type="type === 'password' ? 'text' : type"
      class="prm-input-d"
      placeholder-class="placeholder_font"
      @blur="inputBlur"
      @confirm="inputConfirm"
    >
    <textarea
      v-else
      v-model.trim="inputVal"
      :adjust-position="true"
      :auto-height="autoHeight"
      :focus="focusState"
      :maxlength="(+maxlength)"
      :placeholder="placeholder"
      :placeholder-style="`fontSize: 28rpx;color: rgba(0, 0, 0, 0.25);${pldStyle}`"
      :style="{
        width: `${width ? hasUnit(width) : '100%'}`,
        height: hasUnit(height),
        paddingRight: `${clear ? '80rpx' : '0'}`,
        ...styles,
      }"
      class="prm-input-t"
      disable-default-padding
      @blur="inputBlur"
    />
  </div>
</template>

<style lang="less" scoped>
.prm-input {
  position: relative;
  .prm-input-clear {
    position: absolute;
    top: 20rpx;
    right: 20rpx;
    width: 40rpx;
    height: 40rpx;
    transition: all .3s;
  }
}
/deep/ .placeholder_font {
  color: rgba(0, 0 , 0, 0.25);
}
.prm-input-d, .prm-input-t {
  background: transparent;
  font-size: 28rpx;
}
.prm-input-t {
  padding: 20rpx;
}
</style>
